import { AggregatorImpl } from "../../aggregator/_internal";
import {AsyncAggregator} from "../../async/aggregator";
import { Options, PipelineOperator, ProcessingMode } from "../../core";
import { Iterator } from "../../lazy";
import { AnyObject, Callback } from "../../types";
import { AsyncIterator, AsyncLazy } from "../../async/lazy";

/**
 * Processes multiple aggregation pipelines within a single stage on the same set of input documents.
 *
 * See {@link https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet usage}.
 *
 * @param collection
 * @param expr
 * @param options
 * @returns
 */
export const $facet: PipelineOperator = (
  collection: Iterator|AsyncIterator,
  expr: Record<string, AnyObject[]>,
  options: Options
): Iterator|Promise<AsyncIterator> => {
  if(options.isAsync){
    return (collection as AsyncIterator).transform((async (array: AnyObject[]) => {
    const o: AnyObject = {};
    for (const [k, pipeline] of Object.entries(expr)) {
      o[k] = await(new AsyncAggregator(pipeline, {
        ...options,
        processingMode: ProcessingMode.CLONE_INPUT
      }).run(array));
    }
    // const ps =Object.entries(expr).map(([k, pipeline]) => {
    //   return new AsyncAggregator(pipeline, {
    //     ...options,
    //     processingMode: ProcessingMode.CLONE_INPUT
    //   }).run(array).then((result) => {
    //     o[k] = result;
    //   })
    // })
    return [o];
  })  );
  }
  return (collection as Iterator).transform(((array: AnyObject[]) => {
    const o: AnyObject = {};
    for (const [k, pipeline] of Object.entries(expr)) {
      o[k] = new AggregatorImpl(pipeline, {
        ...options,
        processingMode: ProcessingMode.CLONE_INPUT
      }).run(array);
    }
    return [o];
  }) as Callback<AnyObject[]>);
};
